home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1449.dms / var1449.adf / Devices / Devices.doc < prev    next >
Text File  |  1992-05-03  |  31KB  |  870 lines

  1. 1    DEVICES
  2.  
  3. 1.1  INTRODUCTION
  4.  
  5. The Amiga's operating system must be able to handle input events
  6. from the keyboard or gameports, monitoring the disk drivers,
  7. sending data to the parallel device and communicating with the
  8. serial port, playing stereo sound with its audio chips, etc...
  9. If this was not enough, all these things have to be monitored
  10. in a multitasking environment where several tasks (programs) may
  11. run simultaneously.
  12.  
  13. As you understand this is a very complicated system that
  14. controls all these things. Despite the complexity it must also
  15. be very fast so as little processing time as possible is used.
  16.  
  17. The part of the Amiga which takes care of all these routines
  18. is usually referred as "Exec". Exec handles tasks and task-
  19. switching, interrupts, messages and controls all Amiga's
  20. "devices".
  21.  
  22. In this chapter we will look at how you can, with help of Exec,
  23. control the devices. A device is a collection of special
  24. routines which handles things like disk drivers, serial and
  25. parallel ports, input events, sound generating etc... Although
  26. all these routines are very different they are all handled in
  27. almost the same manner. This means that once you know how to
  28. control one of the devices, you do not need to read much more
  29. before you can control all of them.
  30.  
  31.  
  32.  
  33. 1.2  REQUESTS
  34.  
  35. When you want to do something with a device you fill a "request
  36. block" with your requirements and send it to Exec. Exec will
  37. now take care of everything. Once it has, successfully or not,
  38. completed your request it sends a message to you which tells
  39. you that your request has been completed.
  40.  
  41.  
  42.  
  43. 1.2.1  IOREQUEST
  44.  
  45. The "request block" is actually an IORequest structure defined
  46. in header file "exec/io.h". It looks like this:
  47.  
  48. struct IORequest
  49. {
  50.   struct Message io_Message;
  51.   struct Device  *io_Device;
  52.   struct Unit    *io_Unit;
  53.   UWORD  io_Command;
  54.   UBYTE  io_Flags;
  55.   BYTE   io_Error;
  56. };
  57.  
  58. io_Message: The top part of the request block consists of a
  59.             Message structure. It is used by Exec when the
  60.             request is sent around inside the Amiga. It is
  61.             also used to queue requests at a device's port. 
  62.             You do not need to bother very much about this
  63.             part since Exec takes care of most things. You
  64.             must however initialize it correctly before you
  65.             may start to use the request.
  66.  
  67. io_Device:  Pointer to the device which this request has been
  68.             prepared for. Se below for more information about
  69.             how to initialize a request block.
  70.  
  71. io_Unit:    Some devices, the trackdisk device for example,
  72.             consists of several units (df0:, df1, and so on),
  73.             and this part is used to identify which unit should
  74.             be affected.
  75.  
  76. io_Command: It is here you set your command. There exist both
  77.             standard commands which are handle by most
  78.             devices, but there exist also a lot of special
  79.             unique commands for some devices. See below for
  80.             more information about available commands.
  81.  
  82. io_Flags:   This field is used to set special flags.
  83.  
  84. io_Error:   When the request has been completed you can look
  85.             at this field to see if your request was
  86.             successfully or not completed.
  87.  
  88.  
  89.  
  90. 1.2.2  IOSTDREQ
  91.  
  92. The IORequest structure is the shortest request block you may
  93. use, and consists of only the most important fields. Normally
  94. you need to use a request block which is a bit larger. Since
  95. it is the most commonly used request block, it is called
  96. the "standard request block" (IOStdReq) and is defined like
  97. this: (Also declared in the header file "exec/io.h")
  98.  
  99. struct IOStdReq
  100. {
  101.   struct Message io_Message;
  102.   struct Device  *io_Device;
  103.   struct Unit    *io_Unit;
  104.   UWORD  io_Command;
  105.   UBYTE  io_Flags;
  106.   BYTE   io_Error;
  107.  
  108.   ULONG  io_Actual;
  109.   ULONG  io_Length;
  110.   APTR   io_Data;
  111.   ULONG  io_Offset;
  112. };
  113.  
  114. As you can see the top part is identical to the IORequest
  115. structure, but there have been four extra fields added.
  116.  
  117. io_Actual: When your request has been complete you can look
  118.            here to find the actual number of bytes transferred.
  119.            If this value is not the same as the number of
  120.            bytes you wanted to transfer you know something
  121.            went wrong.
  122.  
  123. io_Length: The number of bytes you want to transfer. If you
  124.            want to continue to send/retrieve information until
  125.            some special external event, set this field to -1.
  126.  
  127. io_Data:   If you are going to send (write) data, this should
  128.            be a pointer to the data that should be sent. If you
  129.            want to retrieve (read) data this should be a
  130.            pointer to a memory buffer were all data which is
  131.            collected should be store.
  132.  
  133. io_Offset: Special offset value used by some devices.
  134.  
  135.  
  136. To make life simpler there exist a special function which will
  137. automatically allocate and preinitialize the request block. The
  138. function is called CreateStdIO(). However, before you may use
  139. this function you have to create a message port to which the
  140. device can communicate with you. Simply use the CreatePort()
  141. function which is described in the "System" manual, chapter
  142. "Messages".
  143.  
  144. CreatePort() allocates and initializes a MsgPort structure.
  145. Normally the message port should only be used by you and the
  146. device, so you do not need to give it any name. The priority
  147. should usually be set to 0 (normal priority).
  148.  
  149.  
  150.   Synopsis: msg_port = CreatePort( name, pri );
  151.   
  152.   msg_port: (struct MsgPort *) Pointer to the new MsgPort
  153.             structure, or NULL if something went wrong.
  154.  
  155.   name:     (char *) Pointer to a string containing the name
  156.             of the message port, or NULL. When working with
  157.             devices you normally do not need to use any name.
  158.   
  159.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure
  160.             that should be allocated.
  161.  
  162.   pri:      (BYTE) This message port's priority. Usually set
  163.             to 0 (normal priority).
  164.  
  165.  
  166. Once you have successfully created the reply port you can
  167. allocate and initialize the standard request block with help
  168. of the CreateStdIO() function. Give it a pointer to the
  169. reply port as the only parameter.
  170.  
  171.   Synopsis: std_req = CreateStdIO( msg_port );
  172.  
  173.   std_req:  (struct IORequest *) Pointer to the new standard
  174.             request block (struct IOStdReq *), or NULL if the
  175.             request block could not be created.
  176.  
  177.   msg_port: (struct MsgPort *) Pointer to the message port
  178.             the device should use to communicate with you.
  179.  
  180.  
  181. When your program terminates you must delete all request
  182. blocks you have created. Use the DeleteStdIO() function.
  183.  
  184.   Synopsis: DeleteStdIO( std_req );
  185.  
  186.   std_req:  (struct IOStdReq *) Pointer to the standard
  187.             request block you want to delete.
  188.  
  189.  
  190. All message ports must also be deleted, but remember to first
  191. deallocate the standard request block to which the message
  192. port is connected to, before you delete the message port itself.
  193.  
  194.   Synopsis: DeletePort( msg_port );
  195.  
  196.   msg_port: (struct MsgPort *) Pointer to the MsgPort structure
  197.             that should be deallocated.
  198.  
  199.  
  200. Here is a short example:
  201.  
  202.   /* Pointer to the standard request block: */
  203.   struct IOStdReq *std_req;
  204.  
  205.   /* Pointer to the message (reply) port: */
  206.   struct MsgPort *msg_port;
  207.  
  208.  
  209.   /* 1. Create a message port so the device can         */
  210.   /*    communicate with us: (No name, normal priority) */
  211.   msg_port = CreatePort( NULL, 0 );
  212.   if( !msg_port )
  213.     clean_up( "ERROR! Could not create message port!" );
  214.  
  215.   /* 2. Allocate and initialize a new standard request block. */
  216.   /* It should use our new message port as reply port:        */
  217.   std_req = CreateStdIO( msg_port );
  218.   if( !std_req )
  219.     clean_up( "ERROR! Could not allocate the request block!" );
  220.  
  221.   ...
  222.  
  223.  
  224.   /* Deallocate standard request block: */
  225.   DeleteStdIO( std_req );
  226.  
  227.   /* Close message port: */
  228.   DeletePort( msg_port );
  229.  
  230.  
  231.  
  232. 1.2.3  IOEXTREQ
  233.  
  234. As if the extra IOStdReq structure would not be enough. There
  235. exist an even larger request block, usually referred as the
  236. "extended request block". This request structure always looks
  237. different depending on which device it is used for. It always
  238. consists of a IORequest structure, or at least the same fields,
  239. at the top, but the rest may vary. See the following chapters
  240. for more information about this request block.
  241.  
  242. Since the size of this extended request block varies you can
  243. not use the CreateStdIO() function to create and initialize it.
  244. Instead you have to use the CreateExtIO() function which will
  245. allocate a request block of any specified size. Except of
  246. allocating a larger request block it will do exactly the same
  247. things as CreateStdIO(). (Remember that you first have to
  248. create a message (reply) port as described above.)
  249.  
  250.   Synopsis: ext_req = CreateExtIO( msg_port, size );
  251.  
  252.   ext_req:  (struct IORequest *) Pointer to the new extended
  253.             request block, or NULL if the request block could
  254.             not be created.
  255.  
  256.   msg_port: (struct MsgPort *) Pointer to the message port
  257.             the device should use to communicate with you.
  258.  
  259.   size:     (long) The number of bytes that should be allocated
  260.             for the extended request block. Use the function
  261.             sizeof() to find the exact number of bytes needed.
  262.  
  263.  
  264. When your program terminates all request block have to be
  265. deleted. Extended request blocks are deleted with the special
  266. DeleteExtIO() function. Once the request block has been deleted
  267. you should also delete the message (reply) port.
  268.  
  269.   Synopsis: DeleteExtIO( std_req, size );
  270.  
  271.   std_req:  (struct IOStdReq *) Pointer to the extended
  272.             request block you want to delete.
  273.  
  274.   size:     (long) The size of the request block, in bytes.
  275.  
  276.  
  277. Here is a short example: (In this example we will use an
  278. extended request block designed for the "serial device".)
  279.  
  280.   /* Pointer to the extended request block: */
  281.   struct IOExtSer *ext_req;
  282.  
  283.   /* Pointer to the message (reply) port: */
  284.   struct MsgPort *msg_port;
  285.  
  286.  
  287.   /* 1. Create a message port so the device can         */
  288.   /*    communicate with us: (No name, normal priority) */
  289.   msg_port = CreatePort( NULL, 0 );
  290.   if( !msg_port )
  291.     clean_up( "ERROR! Could not create message port!" );
  292.  
  293.   /* 2. Allocate and initialize a new extended request block. */
  294.   /* It should use our new message port as reply port, and    */
  295.   /* have the same size as an IOExtSer structure:             */
  296.   ext_req = CreateExtIO( msg_port, sizeof( struct IOExtSer ) );
  297.   if( !ext_req )
  298.     clean_up( "ERROR! Could not allocate the request block!" );
  299.  
  300.   ...
  301.  
  302.  
  303.   /* Deallocate extended request block: (Must be the same */
  304.   /* size as when allocated!)                             */
  305.   DeleteExtIO( ext_req, sizeof( struct IOExtSer ) );
  306.  
  307.   /* Close message port: */
  308.   DeletePort( msg_port );
  309.  
  310.  
  311.  
  312. 1.3  PREPARE THE DEVICE
  313.  
  314. Once you have created a request block you may "open" the device
  315. to which the request block should be connected to. Note that
  316. some devices only need a standard request block (or just a
  317. IORequest structure), but others may need larger extended
  318. request blocks. See the following chapters for more information.
  319.  
  320. To open a device simply use the OpenDevice() function.
  321.  
  322.   Synopsis: error = OpenDevice( name, unit, req, flags );
  323.  
  324.   error:    (long) If OpenDevice() managed to open the device
  325.             it returns 0, else an error number is returned.
  326.  
  327.   name:     (char *) Name of the device you want to open.
  328.             See the following chapters for more information.
  329.  
  330.   unit:     (long) Which unit you want to open. Some devices
  331.             does not have several units and this field is then
  332.             ignored.
  333.  
  334.   req:      (struct IORequest *) Pointer to a request block.
  335.             Note that some devices may need a larger extended
  336.             request blocks.
  337.  
  338.   flags:    (long) Special flags may sometimes be used here,
  339.             otherwise this field is ignored. 
  340.  
  341.  
  342. As usual, everything that you open must be closed before the
  343. program may terminated. To close a device simply call the
  344. CloseDevice() function. After you have closed the device you
  345. should delete the request block and then the message port.
  346. (Unless you want to reopen the device later on.)
  347.  
  348.   Synopsis: CloseDevice( req );
  349.  
  350.   reg:      (struct IORequest *) Pointer to the device's
  351.             request block.
  352.  
  353.  
  354.  
  355. 1.4  STANDARD EXEC COMMANDS
  356.  
  357. There exist eight standard commands which most devices
  358. understand. If the device is already occupied by some other
  359. request, your request is queued on a FIFO basis (First In
  360. First Out). For some devices it may happen that the other
  361. requests are aborted and your started if your request has
  362. higher priority.
  363.  
  364. The eight "standard" commands are:
  365.  
  366.   CMD_RESET  This command will reset the device. All currently
  367.              queued requests are removed (aborted) and the
  368.              device is reinitialized to the default values.
  369.  
  370.   CMD_READ   This command tells the device to start reading
  371.              (collecting) data. The "io_Length" field of the
  372.              request block states how many bytes should be
  373.              read, and the "io_Actual" field will contain the
  374.              number of bytes actually transferred.
  375.  
  376.   CMD_WRITE  This command tells the device to start writing
  377.              (sending) data. The "io_Length" field of the
  378.              request block states how many bytes should be
  379.              written, and the "io_Actual" field will contain
  380.              the number of bytes actually transferred.
  381.  
  382.   CMD_UPDATE This command will update a device in that sense
  383.              that any values still in the internal buffers are
  384.              written out. Most times this is automatically
  385.              done, but this command may be needed when you
  386.              are working with the "trackdisk device" for
  387.              example.
  388.  
  389.   CMD_CLEAR  This command will clear any internal memory
  390.              buffers.
  391.  
  392.   CMD_STOP   When this command is sent to a device all
  393.              communication to and from that device will be
  394.              temporarily halted. Use the "CMD_START" command
  395.              to restart the communication.
  396.  
  397.   CMD_START  This command tells the device to restart the
  398.              communication which has temporarily been halted
  399.              by a "CMD_STOP" command. 
  400.  
  401.   CMD_FLUSH  If this command is sent to a device all currently
  402.              queued requests will be removed (aborted).
  403.  
  404.  
  405. There exist several more commands, but those are device
  406. depending, and may therefore only be used with a certain
  407. device. See the following chapters for more information about
  408. these special device commands.
  409.  
  410.  
  411.  
  412. 1.5  SEND REQUESTS
  413.  
  414. Once you have initialized the request block and "opened" the
  415. desired device, which is described in more details in the
  416. following chapters, you only have to send the request to Exec
  417. and the rest will automatically be done for you. (Isn't that
  418. nice! At last you do not need to worry about everything.)
  419.  
  420. When you send requests to a device the commands can either be
  421. synchronous or asynchronous. When you send synchronous commands
  422. your program is halted until the request has been completed.
  423. With asynchronous commands your program will continue to run
  424. while the device is executing your request.
  425.  
  426.  
  427.  
  428. 1.5.1  SYNCHRONOUS COMMANDS
  429.  
  430. Synchronous commands are very easy to handle. You simply send
  431. your request with the DoIO() function. Your program will
  432. automatically be put to sleep while the device is executing
  433. your command, and once it has finished your program will
  434. wake up. Since your program is put to sleep ("task sleep")
  435. no processing time is waisted while you are waiting for your
  436. request to be completed.
  437.  
  438. Synopsis: error = DoIO( req );
  439.  
  440. error:    (long) DoIO() will return first when the request has
  441.           been completed or something has failed. If the
  442.           request was successfully completed zero is returned,
  443.           else an error number is returned. What error number
  444.           depends on which device was used. See below for a
  445.           complete list of standard error commands.
  446.  
  447. req:      (struct IORequest *) Pointer to the request you
  448.           want to have executed.
  449.  
  450.  
  451.  
  452. 1.5.2  ASYNCHRONOUS COMMANDS
  453.  
  454. Asynchronous requests are a bit more complicated to handle.
  455. Since your program will continue to run while your request is
  456. being executed you do not know when it has been completed. 
  457. Asynchronous requests can be very useful when you do not want
  458. to pause the program while waiting. (It would not be a very
  459. nice game if it was halted each time the user did not move the
  460. joystick for example.)
  461.  
  462. You start asynchronous requests with help of the SendIO()
  463. function.
  464.  
  465. Synopsis: SendIO( req )
  466.  
  467. req:      (struct IORequest *) Pointer to the request you
  468.           want to have executed.
  469.  
  470.  
  471. After you have issued an asynchronous request there exist
  472. three different ways to find out when it has been completed.
  473.  
  474.  
  475.  
  476. 1.5.2.1  KEEP ON CHECKING THE REQUEST UNTIL IT HAS BEEN COMPLETED
  477.  
  478. You can use the CheckIO() function which will either return
  479. NULL if the request has not been completed, or it will return
  480. a pointer to the request if it has been completed.
  481.  
  482. Synopsis: ptr = CheckIO( req );
  483.  
  484. ptr:      (long) CheckIO() will either return NULL if the
  485.           request have not been completed or it will return a
  486.           pointer to the request block.
  487.  
  488. req:      (struct IORequest *) Pointer to the request you
  489.           want to check.
  490.  
  491.  
  492. When a request has been completed a message is sent to a
  493. specified reply port. Note that CheckIO() will not remove the
  494. message at the reply port. This should be done with the
  495. Remove() function.
  496.  
  497. Synopsis: Remove( node );
  498.  
  499. node:     (struct Node *) Pointer to the node that should be
  500.           removed.
  501.  
  502.  
  503.  
  504. 1.5.2.2  WAIT FOR THE REQUEST TO BE COMPLETED
  505.  
  506. You can put your program to sleep and wait for the request to
  507. be completed, by calling the WaitIO() function. WaitIO() will
  508. automatically remove the message at the reply port.
  509.  
  510. Synopsis: error = WaitIO( req );
  511.  
  512. error:    (long) WaitIO() will return first when the request,
  513.           that has previously been sent, has been completed or
  514.           something has failed. If the request was successfully
  515.           completed zero is returned, else an error number is
  516.           returned. What error number depends on which device
  517.           was used.
  518.  
  519. req:      (struct IORequest *) Pointer to the request you
  520.           want to wait for to be completed. Note that the
  521.           request must have already been sent to the device
  522.           by either a SendIO() or BeginIO() function call. If
  523.           the request has already been completed WaitIO() will
  524.           immediately return.
  525.  
  526.  
  527.  
  528. 1.5.2.4  WAIT FOR A REPLY MESSAGE
  529.  
  530. Since a message is sent to the request block's reply port each
  531. time the request has been completed you can simply wait for a
  532. message to arrive. The simplest way is to use the WaitPort()
  533. function which will put your program to sleep while waiting
  534. for a message to arrive at the specified port. Note that it
  535. will not remove the message.
  536.  
  537. Synopsis: msg = WaitPort( msg_port );
  538.  
  539. msg:      (struct Message *) Pointer to the first message which
  540.           has arrived. Remember that this function will not
  541.           remove the message from the queue. Use the Remove()
  542.           function to do this.
  543.  
  544. msg_port: (struct MsgPort *) Pointer to the message port which
  545.           you want to monitor. Your program will be put to
  546.           sleep while waiting, and if no message arrive it
  547.           will never wake up, so be careful.
  548.  
  549.  
  550. Instead of just waiting for one request to be completed you
  551. can wait fore several ones at the same time. This is extremely
  552. useful if your program is handling a lot of requests
  553. simultaneously. Now we need to use the multipurpose Wait()
  554. function which is described in the "System" manual, chapter
  555. "Messages".
  556.  
  557. Synopsis: rsig = Wait( wsig )
  558.  
  559. rsig:     (ULONG) When one of the specified signal bits was
  560.           received, the task is woken up and Wait() returns
  561.           the signal bit value that woke it up.
  562.  
  563. wsig:     (ULONG) The signals we are waiting for. Wait() will
  564.           put the task to sleep, and it will only wake up if
  565.           one of the specified signal bit values is received.
  566.  
  567.  
  568.  
  569. 1.5.4  QUICK I/O
  570.  
  571. Although the system with sending requests and messages is very
  572. fast it may sometimes not be fast enough. If you want to handle
  573. a lot of data extremely fast you can try to use the "Quick
  574. mode". When you are using this quick mode Exec tries to skip
  575. all routines that are not essential. No messages are sent, and
  576. there is no checking etc...
  577.  
  578. The quick mode should only be used when really needed, and it
  579. can not always be used. When you want to try to use the quick
  580. mode set the IOF_QUICK flag in the "io_Flags" field of the
  581. request block. To pass the request to Exec you should not use
  582. the DoIO() or SendIO() functions, but instead the low level
  583. function BeginIO().
  584.  
  585.   Synopsis: BeginIO( req )
  586.  
  587.   req:      (struct IORequest *) Pointer to the request you
  588.             want to have executed. When you want to use the
  589.             quick mode you have to use this low level function
  590.             rather than SendIO() and DoIO().
  591.  
  592.  
  593. If we were allowed to use the quick mode the request will be
  594. synchronous. (Your program is put to sleep since all computer
  595. time is needed to run this fast quick mode.)
  596.  
  597. If we were not allowed to use the quick mode the request will
  598. be asynchronous, and is then handled exactly the same as if the
  599. request had been sent by a SendIO() call.
  600.  
  601. After you have posted your quick request you must check if you
  602. were allowed to use this fast mode or not. If not you have to
  603. wait for the request to be completed and remove the reply
  604. message yourself. To check if you were allowed quick mode or
  605. not simply look at the "io_Flags" field of the request block to
  606. see if the flag IOF_QUICK is still there or not. If the flag is
  607. still set the request was using the quick mode, and you do not
  608. need to do anything more. If the flag is not there any more,
  609. you were not allowed quick mode, and thus you have to wait for
  610. the asynchronous request to be completed and remove the message
  611. yourself.
  612.  
  613.  
  614.   /* Initialize the request block as normal. */
  615.   /* The pointer to it is called "ioreq".    */
  616.   /* ...                                     */
  617.  
  618.   /* Try to use the "quick" mode: */
  619.   ioreq->IOSer.io_Flags = IOF_QUICK;
  620.  
  621.   /* Do the request: */
  622.   BeginIO( ioreq );
  623.  
  624.   /* Check if the flag IOF_QUICK is still there or not: */
  625.   if( (ioreq->IOSer.io_Flags & IOF_QUICK) )
  626.   {
  627.     /* OK! The request was using quick mode, which means    */
  628.     /* that our task was put to sleep while the request was */
  629.     /* executed, and the request has now been completed.    */
  630.     /* Since we are using quick mode there are no message   */
  631.     /* that should be removed.                              */
  632.   }
  633.   else
  634.   {
  635.     /* Too bad, we were not allowed to use the quick mode. */
  636.     /* The request should now be treated as if it was      */
  637.     /* started with a SendIO() function call. This request */
  638.     /* is asynchronous - request returns immediately.      */
  639.   
  640.     /* Wait for the request to be completed. WaitIO() will */
  641.     /* also automatically remove the message at the reply  */
  642.     /* port.                                               */
  643.     WaitIO( ioreq );
  644.   }
  645.  
  646.  
  647.  
  648. 1.5.3  ABORT REQUESTS
  649.  
  650. You can abort a previously started request by calling the
  651. AbortIO() function. Of course, only asynchronous commands can
  652. be aborted, and if the request has already been completed it
  653. can not be aborted any more.
  654.  
  655.   Synopsis: AbortIO( req )
  656.  
  657.   req:      (struct IORequest *) Pointer to the request you
  658.             want to abort.
  659.  
  660.  
  661.  
  662. 1.6  ERRORS
  663.  
  664. No one is perfect, and even the devices may sometimes not be
  665. able to do what you tell them to do (usually because you have
  666. done something wrong). If something goes fails an error number
  667. is returned. Each device has it own set of unique error codes
  668. which are described in the following chapters. There exist,
  669. however, four error codes that are sent by Exec. (They are all
  670. defined in the header file "exec/errors.h")
  671.  
  672. IOERR_OPENFAIL  The device (unit) could not be opened. If you
  673.                 receive this message there is normally some
  674.                 other program currently using the device with
  675.                 exclusive mode.
  676.  
  677. IOERR_ABORTED   When you abort a previously started request by
  678.                 calling the AbortIO() function, the io_Error
  679.                 filed of that request is set to IOERR_ABORTED.
  680.                 If you find a request block with this flag set,
  681.                 you know that it has been aborted.
  682.  
  683. IOERR_NOCMD     You tried to use a command that is not
  684.                 supported by that device.
  685.  
  686. IOERR_BADLENGTH The length of the request was not valid.
  687.  
  688.  
  689.  
  690. 1.7  DEVICES
  691.  
  692. There exist a lot of different devices each specialized to do
  693. something unique. Some devices are so called "low level
  694. devices" and are handling a lot of fresh untranslated raw
  695. data which will be modified and later used by other so called
  696. "high level devices".
  697.  
  698. In total there exist 12 devices (14 with the new V2.05 operating
  699. system) which all will be described in a chapter each. Although
  700. the devices are so different, they all are handled in much the
  701. same manner - allocate a message port and a request block, open
  702. the device and start to send your request, finally close
  703. everything and quit.
  704.  
  705. Five devices are not covered in this edition, but will soon be
  706. added. All registered members will receive more information
  707. about this as soon as the chapters have been completed.
  708.  
  709.  
  710.  
  711. 1.7.1  Timer Device
  712.  
  713. The Timer Device can be used if you want to receive a message
  714. after a specified time limit. This is one of the so called "low
  715. level devices", and is used by many other devices. Although the
  716. timer device does not sound very interesting, it can really be
  717. useful.
  718.  
  719.  
  720.  
  721. 1.7.2  Gameport Device
  722.  
  723. The Gameport Device is a smart little device which reads data
  724. from the two gameport connectors on the Amiga. The device
  725. can handle both normal Joystick as well as Mouse movements.
  726. Even light-pens and other input devices may be connected and
  727. monitored by this device. These special input devices must
  728. however have its own drivers which translates the signals to
  729. for the gameport device understandable form.
  730.  
  731.  
  732.  
  733. 1.7.3  Audio Device
  734.  
  735. The Audio Device is used to produce sound. It monitors the four
  736. hardware sound channels, and can therefore play the sound in
  737. stereo. Everything from a simple beep to complete songs may be
  738. played. The audio device can both produce sounds itself or
  739. directly play sampled (digitized) sound effects.
  740.  
  741. Sound is an important part of our life and should therefore
  742. in my opinion also be used a lot in computer programs. Sound
  743. can be used in most situations, from emergency beeps to
  744. entertaining melodies.
  745.  
  746.  
  747.  
  748. 1.7.4  Narrator Device
  749.  
  750. The Amiga is not only extremely good at producing high quality
  751. sound. with help of the Narrator Device it can also speak
  752. almost as a human. Although it is not a Frank Sinatra, it is
  753. possible to understand what it is saying, and this can be used
  754. in many situations. Used with care, it is possible to produce
  755. very good sound.
  756.  
  757. Sadly, somehow many persons do not like this unique feature of
  758. the Amiga, and very few programs support the narrator device. I
  759. believe that artificial speech can be used in many situations,
  760. and can really be handy for the user. Most "professional"
  761. programs would really benefit from using the narrator device.
  762.  
  763.  
  764.  
  765. 1.7.5  Trackdisk Device
  766.  
  767. With help of the Trackdisk Device you can directly access the
  768. disk drivers. Data can not only be transferred to and from the
  769. disks, but you may even format specific sectors of a disk and
  770. do a lot of other low level stuff.
  771.  
  772.  
  773.  
  774. 1.7.6  Serial Device   
  775.  
  776. The Serial Device is used to transfer data from and to the
  777. serial port. It can be used at different speeds (bauds) and
  778. use seven or eight bit characters. The device also support
  779. parity (error) checking.
  780.  
  781.  
  782.  
  783. 1.7.7  Parallel Device
  784.  
  785. The Parallel device is used to transfer data from and to the
  786. parallel port. The parallel device is very useful when you
  787. want very fast communications, and is therefore often used by
  788. sound samplers and video digitizers. However, the most commonly
  789. used external device is without question a printer, but you
  790. should then use the printer device which has specially been
  791. designed for this purpose.
  792.  
  793.  
  794.  
  795. 1.7.8  Printer Device
  796.  
  797. The printer device can use both the serial and parallel device
  798. depending on to which port the printer is connected to. With
  799. the printer device you can not only print normal text, special
  800. printer commands may be sent and you can even print graphics
  801. with it.
  802.  
  803. The printer device uses the preferences settings to find out
  804. to which port the printer is connected, what printer it is,
  805. and other special settings like margins, paper length etc...
  806.  
  807.  
  808.  
  809.  
  810. 1.7.9  Keyboard Device
  811.  
  812. The Keyboard Device is a "low level device" which is used by
  813. the "Input Device". The keyboard device collects untranslated
  814. (raw) key codes. This device is very fast and uses very little
  815. computer time.
  816.  
  817. This device will be covered in the next version of the manual.
  818. All registered members will receive more information as soon as
  819. the next version has been completed.
  820.  
  821.  
  822.  
  823. 1.7.10  Input Device
  824.  
  825. The Input Device is a so called "high level device" which
  826. receives information from the timer, keyboard and gameport
  827. devices, and puts all this information into one single input
  828. stream. Very handy and useful device.
  829.  
  830. This device will be covered in the next version of the manual.
  831. All registered members will receive more information as soon as
  832. the next version has been completed.
  833.  
  834.  
  835.  
  836. 1.7.11  Console Device
  837.  
  838. The Console Device enables you to handle input and output as
  839. an intelligent terminal for ASCII characters. Works very close
  840. with Intuition, and is also a very handy and useful device.
  841.  
  842. This device will be covered in the next version of the manual.
  843. All registered members will receive more information as soon as
  844. the next version has been completed.
  845.  
  846.  
  847. 1.7.12  Clipboard Device
  848.  
  849. With the Clipboard Device data can be cut, pasted and copied
  850. between different programs. Several clips may be used
  851. simultaneously, and the device supports the IFF standard.
  852.  
  853. This device will be covered in the next version of the manual.
  854. All registered members will receive more information as soon as
  855. the next version has been completed.
  856.  
  857.  
  858.  
  859. 1.7.13  SCSI AND PCMCIA DEVICE
  860.  
  861. There exist two new devices. The SCSI device is only available
  862. with the new V2.0 operating system, and the PCMCIA device exist
  863. for the moment only on Amiga 600.
  864.  
  865. These device will be covered in the next version of the manual.
  866. All registered members will receive more information as soon as
  867. the next version has been completed.
  868.  
  869.  
  870.